/**
  ******************************************************************************
  * @file    AT25DF041.c 
  * @author  Thongnh
  * @version V1.0
  * @date    18-07-2011
  * @brief   Main process of flash AT25DF041
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, XICUTELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 Xicutelectronics</center></h2>
  ******************************************************************************
  */ 
#include "StrLib.h"
#include "AT25DF041.h"
#include "User.h"
#include "Config.h"

U16 cUser::s_TotalUser;
U32 cUser::s_UserReadMark[USER_READ_MARK_MAX_CNT];

void cUser::InitReset()
{
    s_TotalUser = cConfig::GetTotalUser();
}


void cUser::IncTotalUser()
{
    if (USER_MAX_CNT > s_TotalUser) 
    {
        ++s_TotalUser;
        cConfig::SetTotalUser(s_TotalUser);
    }
}

void cUser::DecTotalUser(bool bEraseAll)
{
    if (true == bEraseAll) 
    {
        s_TotalUser = 0;
        cConfig::SetTotalUser(s_TotalUser);
    }
    else if (0 < s_TotalUser) 
    {
        --s_TotalUser;
        cConfig::SetTotalUser(s_TotalUser);
    }
}

bool cUser::Lookup(U8 *pCard, U32 &iAddr, U16 &userID)
{
    U16 userCount = 0;
    U8  card[USER_LENGTH];

    iAddr = USER_BLOCK_ADDR;
    while (userCount < s_TotalUser)
    {
        if (VALID_USER == cFlash::ReadByte(iAddr))
        {
            cFlash::Read(iAddr, card, USER_LENGTH);
            if (true == cStrLib::Strcmp(pCard, &card[1], 4))
            {
                pCard[4] = card[5];
                pCard[5] = card[6];
                userID = userCount;
                return (true);
            }
            ++userCount;
        }

        iAddr += USER_LENGTH;
        if ((USER_BLOCK_ADDR + USER_BLOCK_SIZE) <= iAddr)
        {
            return (false);
        }
    }
    return (false);
}


bool cUser::FindFree(U32 &iAddr)
{
    U8 card[USER_LENGTH];

    iAddr = USER_BLOCK_ADDR;
    while ((USER_BLOCK_ADDR + USER_BLOCK_SIZE) > iAddr)
    {
        cFlash::Read(iAddr, card, USER_LENGTH);
        if (true == cStrLib::StrCmpWithConst(card, 0xFF, USER_LENGTH))
        {
            return (true);
        }
        iAddr += USER_LENGTH;
    }
    return (false);
}

bool cUser::FindUser(U32 iCardCode, U16 &timeZone, U16 &userID)
{
    U32 addr;
    U8  pCard[USER_LENGTH];
    bool tempReturn;

    for (U8 i=0; i<USER_LENGTH; i++)
    {
        pCard[i] = 0;
    }
    pCard[0] = (U8)(iCardCode>>24);
    pCard[1] = (U8)(iCardCode>>16);
    pCard[2] = (U8)(iCardCode>>8);
    pCard[3] = (U8)(iCardCode);

    tempReturn = Lookup(pCard, addr, userID);
    timeZone = 0;
    if (true == tempReturn)
    {
        timeZone = (((U16)pCard[4])<<8) | ((U16)pCard[5]);
    }
    return (tempReturn);
}


bool cUser::Register(U32 iCardCode, U16 iTimeZone)
{
    U32 addr;
    U8  card[USER_LENGTH];

    //if (false == Lookup(pCard, addr))
    //{
    if (true == FindFree(addr))
    {
        for (U8 i=0; i<USER_LENGTH; i++)
        {
            card[i] = 0;
        }
        card[0] = VALID_USER;
        card[1] = (U8)(iCardCode>>24);
        card[2] = (U8)(iCardCode>>16);
        card[3] = (U8)(iCardCode>>8);
        card[4] = (U8)(iCardCode);
        card[5] = (U8)(iTimeZone>>8);
        card[6] = (U8)(iTimeZone);
        cFlash::Write(addr, card, USER_LENGTH);
        IncTotalUser();
        return (true);
    }
    //}
    return (false);
}


bool cUser::Register(U8 *pCard)
{
    U32 addr;
    U8  card[USER_LENGTH];

    //if (false == Lookup(pCard, addr))
    //{
    if (true == FindFree(addr))
    {
        card[0] = VALID_USER;
        cStrLib::Strcpy(&card[1], pCard, USER_LENGTH - 1);
        cFlash::Write(addr, card, USER_LENGTH);
        IncTotalUser();
        return (true);
    }
    //}
    return (false);
}


bool cUser::Erase(U8 *pCard)
{
    U32 addr;
	U16 userID;

    if (true == Lookup(pCard, addr, userID))
    {
        cFlash::WriteByte(addr, ERASE_USER);
        DecTotalUser(false);
        return (true);
    }
    return (false);
}

bool cUser::EraseAll()
{
    cFlash::EraseBlock(cFlash::BLOCK_ERASE_64K, USER_BLOCK_ADDR);
    DecTotalUser(true);
    return (true);
}


void cUser::ResetUserReadMark()
{
    for (U16 i=0; i<USER_READ_MARK_MAX_CNT; i++)
    {
        s_UserReadMark[i] = 0;
    }
}


void cUser::SetUserRead(U16 iUserID)
{
    U16 dwordIndex = iUserID / 32;
    U16 bitIndex = iUserID % 32;

    s_UserReadMark[dwordIndex] |= 1<<bitIndex;
}


bool cUser::IsUserRead(U16 iUserID)
{
    U16 dwordIndex = iUserID / 32;
    U16 bitIndex = iUserID % 32;
    U32 userReadMask = (1<<bitIndex);

    if ( 0 != (s_UserReadMark[dwordIndex] & userReadMask) )
    {
        return (true);
    }
    return (false);
}


// end of file

